home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Frameworks / TransSkel 3.24 / Demos / C Demos / MultiSkel / MSkelRgn.c < prev    next >
Text File  |  1994-07-14  |  5KB  |  223 lines

  1. /*
  2.  * TransSkel multiple-window demonstration: Region module
  3.  *
  4.  * This module handles a window in which the mouse may be clicked and
  5.  * dragged to draw rectangles.  The rects so drawn are combined into
  6.  * a single region, the outline of which is drawn.  Rects drawn while
  7.  * the shift key is held down are subtracted from the region.
  8.  * Double-clicking the mouse clears the display.  If the window is
  9.  * resized, the region that is drawn is resized as well.
  10.  *
  11.  * BUG: should measure double-click time from mouse-up to next mouse down,
  12.  * not time between mouse-downs.
  13.  *
  14.  * 21 Apr 88 Paul DuBois
  15.  * 08 Jul 88
  16.  * - Changed outline so that it's drawn as a marquee.
  17.  * 29 Jan 89
  18.  * - Conversion for TransSkel 2.0.
  19.  * 12 Jan 91
  20.  * - Conversion for TransSkel 3.0.
  21.  */
  22.  
  23. # include    "TransSkel.h"
  24.  
  25. # include    "MultiSkel.h"
  26.  
  27.  
  28. static Rect            rgnPortRect;    /* portRect size - for detecting wind grows */
  29. static RgnHandle    selectRgn;        /* current region to be drawn */
  30. static long            selectWhen;        /* time of last click */
  31. static Point        selectWhere;    /* location of last click */
  32.  
  33. static Pattern        marqueePat = { 0x0f, 0x87, 0xc3, 0xe1, 0xf0, 0x78, 0x3c, 0x1e };
  34.  
  35.  
  36. static void
  37. MarqueeRgn (RgnHandle r)
  38. {
  39. PenState    p;
  40. Byte        b;
  41. short        i;
  42.  
  43.     GetPenState (&p);
  44.     PenPat ((ConstPatternParam) &marqueePat);
  45.     PenMode (patCopy);
  46.     FrameRgn (r);
  47.     SetPenState (&p);
  48.     b = ((char *) &marqueePat)[0];        /* shift pattern for next call */
  49.     for (i = 0; i < 7; ++i)
  50.         ((char *) &marqueePat)[i] = ((char *) &marqueePat)[i+1];
  51.     ((char *) &marqueePat)[7] = b;
  52. }
  53.  
  54.  
  55. /*
  56.  * While mouse is down, draw gray selection rectangle in the current
  57.  * port.  Return the resultant rect in dstRect.  The rect is always
  58.  * clipped to the current portRect.
  59.  */
  60.  
  61. static void
  62. DoSelectRect (Point startPoint, Rect *dstRect)
  63. {
  64. Point        pt, dragPt;
  65. Rect        rClip;
  66. GrafPtr        port;
  67. Boolean        result;
  68. PenState    ps;
  69. short        i;
  70.  
  71.     GetPort (&port);
  72.     rClip = port->portRect;
  73.     rClip.right -= 15;
  74.     GetPenState (&ps);
  75.     PenPat ((ConstPatternParam) &qd.gray);
  76.     PenMode (patXor);
  77.     dragPt = startPoint;
  78.     Pt2Rect (dragPt, dragPt, dstRect);
  79.     FrameRect (dstRect);
  80.     for (;;)
  81.     {
  82.         GetMouse (&pt);
  83.         if (!EqualPt (pt, dragPt))    /* mouse has moved, change region */
  84.         {
  85.             FrameRect (dstRect);
  86.             dragPt = pt;
  87.             Pt2Rect (dragPt, startPoint, dstRect);
  88.             result = SectRect (dstRect, &rClip, dstRect);
  89.             FrameRect (dstRect);
  90.             for (i = 0; i < 1000; ++i) { /* empty */ }
  91.         }
  92.         if (!StillDown ()) break;
  93.     }
  94.     FrameRect (dstRect);    /* erase last rect */
  95.     SetPenState (&ps);
  96. }
  97.  
  98.  
  99. /*
  100.  * On double-click, clear window.  On single click, draw gray selection
  101.  * rectangle as long as mouse is held down.  If user draws non-empty rect,
  102.  * then add it to the selection region and redraw the region's outline.
  103.  * If the shift-key was down, then subtract the selection region instead
  104.  * and redraw.
  105.  */
  106.  
  107. static pascal void
  108. Mouse (Point pt, long t, short mods)
  109. {
  110. Rect        r;
  111. RgnHandle    rgn;
  112.  
  113.     r = rgnWind->portRect;
  114.     if (pt.h >= r.right - 15)        /* must not click in right edge */
  115.         return;
  116.     if (t - selectWhen <= GetDblTime ())    /* it's a double-click */
  117.     {
  118.         selectWhen = 0L;        /* don't take next click as double-click */
  119.         SetWindClip (rgnWind);
  120.         EraseRgn (selectRgn);
  121.         ResetWindClip ();
  122.         SetEmptyRgn (selectRgn);    /* clear region */
  123.     }
  124.     else
  125.     {
  126.         selectWhen = t;                /* update click variables */
  127.         selectWhere = pt;
  128.         DoSelectRect (pt, &r);    /* draw selection rectangle */
  129.         if (!EmptyRect (&r))
  130.         {
  131.             EraseRgn (selectRgn);
  132.             selectWhen = 0L;
  133.             rgn = NewRgn ();
  134.             RectRgn (rgn, &r);
  135.             if ((mods & shiftKey) != 0)        /* test shift key */
  136.                 DiffRgn (selectRgn, rgn, selectRgn);
  137.             else
  138.                 UnionRgn (selectRgn, rgn, selectRgn);
  139.             DisposeRgn (rgn);
  140.         }
  141.     }
  142. }
  143.  
  144.  
  145. static pascal void
  146. Idle (void)
  147. {
  148. short    i;
  149.  
  150.     SetWindClip (rgnWind);
  151.     MarqueeRgn (selectRgn);    /* draw selection region outline */
  152.     ResetWindClip ();        /* restore previous clipping */
  153. }
  154.  
  155.  
  156. /*
  157.  * Redraw the current region.  If the window was resized, resize
  158.  * the region to fit.
  159.  */
  160.  
  161. static pascal void
  162. Update (Boolean resized)
  163. {
  164. Rect    r;
  165.  
  166.     r = rgnWind->portRect;
  167.     EraseRect (&r);
  168.     if (resized)
  169.     {
  170.         rgnPortRect.right -= 15;    /* don't use right edge of window */
  171.         r.right -= 15;
  172.         MapRgn (selectRgn, &rgnPortRect, &r);
  173.         rgnPortRect = rgnWind->portRect;
  174.     }
  175.     DrawGrowBox (rgnWind);
  176.     Idle ();
  177. }
  178.  
  179.  
  180. static pascal void
  181. Activate (Boolean active)
  182. {
  183.     DrawGrowBox (rgnWind);
  184.     if (active)
  185.         DisableItem (editMenu, 0);
  186.     else
  187.         EnableItem (editMenu, 0);
  188.     DrawMenuBar ();
  189. }
  190.  
  191.  
  192. static pascal void
  193. Clobber (void)
  194. {
  195.     DisposeRgn (selectRgn);
  196.     DisposeWindow (rgnWind);
  197. }
  198.  
  199.  
  200. void
  201. RgnWindInit (void)
  202. {
  203.     if (SkelQuery (skelQHasColorQD))
  204.         rgnWind = GetNewCWindow (rgnWindRes, nil, (WindowPtr) -1L);
  205.     else
  206.         rgnWind = GetNewWindow (rgnWindRes, nil, (WindowPtr) -1L);
  207.     if (rgnWind == (WindowPtr) nil)
  208.         return;
  209.     (void) SkelWindow (rgnWind,
  210.                 Mouse,        /* draw rectangles */
  211.                 nil,        /* ignore keyclicks */
  212.                 Update,
  213.                 Activate,
  214.                 nil,        /* no close proc */
  215.                 Clobber,    /* disposal proc */
  216.                 Idle,        /* idle proc */
  217.                 false);
  218.  
  219.     rgnPortRect = rgnWind->portRect;
  220.     selectRgn = NewRgn ();    /* selected region empty initially */
  221.     selectWhen = 0L;        /* first click can't be taken as dbl-click */
  222. }
  223.